import chalk from "chalk"
import path, { resolve, dirname, join } from "node:path"
import { fileURLToPath } from "node:url";
import jetpack from "fs-jetpack"
import fs from 'fs-extra'
import { stdout, stderr } from "single-line-log"

export function warn(msg: string) {
  console.log(`${chalk.bgRed("WARN")} : ${msg}`);
}

export function success(msg: string) {
  console.log(`${chalk.blue("SUCCESS")} : ${msg}`);
}

export function* progress(msgArr: string[]) {
  let len = msgArr.length
  for (const i in msgArr) {
    let msg = msgArr[i]
    let percent = ((Number(i) + 1) / len * 100).toFixed(2)
    yield stdout(`${percent}% ${msg}\n`);
    if (Number(i) === len - 1) {
      console.log("");
      // stderr("asd")
    }
  }
}

export function getArgs() {
  process.argv.splice(0, 2)
  return process.argv
}

export function removeDir(path: string, exclude?: string[]) {
  if (exclude && dirIsExist(path)) {
    let files = fs.readdirSync(path)
    files.forEach(name => {
      if (!exclude.includes(name)) {
        jetpack.remove(`${path}/${name}`)
      }
    })
  } else {
    jetpack.remove(path)
  }
  return true
}

export function getDirName() {
  return dirname(fileURLToPath(import.meta.url))
}

export function createFile(path: string, data: string) {
  fs.writeFileSync(path, data, { encoding: 'utf8' })
}

export function copyFile(
  src: string,
  dest: string,
  filename?: string,
  cb?: (data: string, filename: string) => string) {
  const stat = fs.statSync(src)
  if (stat.isDirectory()) copyDir(src, dest, cb);
  else {
    if (!cb) fs.copyFileSync(src, dest)
    else {
      // 图片直接粘贴
      if (isImg(filename || path.basename(src))) {
        return fs.copyFileSync(src, dest)
      };
      let data = fs.readFileSync(src, { encoding: 'utf8' })
      data = cb(data, filename || path.basename(src))
      createFile(dest, data)
    }
  }
}

export function copyDir(
  srcDir: string,
  destDir: string,
  cb?: (data: string, filename: string) => string,
  filterArr?: string[]) {
  // 1 创建目录
  fs.mkdirSync(destDir, { recursive: true })
  // 2 循环复制
  const FileArr = filterCharacter(fs.readdirSync(srcDir), filterArr || [".git"])
  for (let file of FileArr) {
    const destFileName = filterFile(file)
    const srcFile = resolve(srcDir, file)
    const destFile = resolve(destDir, destFileName)
    copyFile(srcFile, destFile, file, cb)
  }
}

export function isImg(name: string) {
  return /\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga|webp)$/g.test(name)
}

// 过滤字符
export function filterCharacter(arr: string[], filterArr: string[]): string[] {
  return arr.filter(v => (!filterArr.includes(v)))
}
// 过滤文件进行重名
export function filterFile(str: string) {
  const FILTERARR = ["_gitignore"]
  if (FILTERARR.includes(str)) str = str.replace("_", ".")
  return str
}

export function dirToJson(dirPath: string) {
  const obj: Record<string, string[]> = {}
  for (const file of fs.readdirSync(dirPath, { withFileTypes: true })) {
    if (file.isDirectory()) {
      const NAME = file.name
      // 1 获取 - 前面的字段
      const prop = NAME.match(/(\w+)-/)
      // 2 如果 prop 存在
      if (prop) {
        obj[prop[1]] ? obj[prop[1]].push(NAME) : (obj[prop[1]] = [NAME])
      } else {
        obj[NAME] ? obj[NAME].push(NAME) : (obj[NAME] = [NAME])
      }
    }
  }
  return obj
}

export function dirToArr(dirPath: string) {
  const arr: string[] = []
  for (const file of fs.readdirSync(dirPath, { withFileTypes: true })) {
    if (file.isDirectory()) {
      const NAME = file.name
      arr.push(NAME)
    }
  }
  return arr
}

export function dirIsExist(dirPath: string) {
  try {
    return fs.statSync(dirPath).isDirectory()
  } catch (error) {
    return false
  }
}
export function fileIsExist(path: string) {
  try {
    let res = fs.statSync(path)
    console.log(res);
    console.log(res.isDirectory());
    return res && !res?.isDirectory()
  } catch (error) {
    return false
  }
}

export function renameDir(oldPath: string, newPath: string) {
  if (dirIsExist(oldPath)) {
    fs.renameSync(oldPath, newPath);
  } else {
    handleError(new Error(`renameDir error: ${oldPath}`))
  }
}

export function invokeWithErrorHandling(handler: Function, args: null | any[], context: any = undefined, info?: string) {
  try {
    return args ? handler.apply(context, args) : handler.call(context)
  } catch (e: any) {
    handleError(e)
  }
}

export function handleError(err: Error) {
  console.log(chalk.red(`${err.message}`));
  console.log(chalk.bgRed('UNHANDLER ERROR! 🐱‍🏍 Shuting dow...'));
  process.exit(1);
}
